import pygame
import platform

from Core.CScene import Scene
from Core.CImage import Image
from Core.CText import Text

class MainScene(Scene):

  def __init__(self, datafile, screensize, audio, variables = None):
    print 'loading', datafile
    self.__file = open(datafile, 'r')
    self.__screensize = screensize
    self.__audio = audio

    if variables == None:
      self.__variables = dict()
    else:
      self.__variables = variables

    self.setup()
    self.nextSection()

  #generic scene functions
  def draw(self, graphics):
    if self.__background is not None:
      self.__background.draw(graphics, [0, 0])

    if self.__displayed[0] is not None:
      self.__displayed[0].draw(graphics, [50, 50])

    if self.__displayed[1] is not None:
      x = self.__screensize[0]/2 - self.__displayed[1].size()[2]/2
      self.__displayed[1].draw(graphics, [x, 50])

    if self.__displayed[2] is not None:
      x = self.__screensize[0] - self.__displayed[2].size()[2] - 50
      self.__displayed[2].draw(graphics, [x, 50])

    if self.__textBox:
      self.__textBox.draw(graphics, [62, 568])

    if self.__name is not None:
      self.__name.draw(graphics, [70, 574])

    if self.__text is not None:
      self.__text.draw(graphics, [70, 601])

    if len(self.__options) > 0:
      yoffset = 2 #slightly more spacious than regular text
      for option in self.__options:
        option[0].draw(graphics, [80, 606 + self.__text.getHeight() + yoffset])
        yoffset += option[0].getHeight() + 2

  def update(self, time):
    if self.__background is not None:
      self.__background.update(time)

    if self.__displayed[0] is not None:
      self.__displayed[0].update(time)

    if self.__displayed[1] is not None:
      self.__displayed[1].update(time)

    if self.__displayed[2] is not None:
      self.__displayed[2].update(time)

  def mouseInput(self, button, pos):
    if button == 0:
      yoffset = 2
      for option in self.__options:
        if pos[0] >= 80 and pos[0] <= 80 + option[0].getWidth():
          if pos[1] >= 606 + self.__text.getHeight() + yoffset and pos[1] <= 606 + self.__text.getHeight() + yoffset + option[0].getHeight():
            self.__index = option[1]
            self.__options = []
            n, d, t, p, o = self.__sections[self.__currentsection-1] #name, displayed, text, played, options
            t.append(option[0]) #answer
            self.__sections[self.__currentsection-1] = (n, d, t, p, [])
            break
        yoffset += option[0].getHeight() + 2
      return self.nextSection()
    if button == 1:
      self.previousSection()

  #scene specific functions start here
  def setup(self):
    self.__text = None
    self.__options = []
    self.__lastoptionline = 0
    self.__name = None
    self.__played = []
    self.__displayed = [None, None, None]
    self.__currentsection = 0
    self.__sections = []
    self.__f = pygame.font.Font(None, 32)
    self.__index = -1
    self.__lines = []
    self.__endlinemode = None
    self.__textBox = Image("../data/graphics/textbox.png")

    for line in self.__file:
      self.__lines.append(line)
    self.__file.close()

    data = self.readLine()
    tempnames = self.split(data, "\"")
    self.__names = []
    for name in tempnames:
      if len(name) > 0:
        self.__names.append(Text(name, self.__f, self.__screensize[0]))

    data = self.readLine()
    tempimages = self.split(data, "\"")
    self.__images = []
    for img in tempimages:
      if len(img) > 1:
        self.__images.append(Image("../data/graphics/" + img))

    data = self.readLine()
    self.__music = self.split(data, "\"")
    if len(self.__music) > 0 and len(self.__music[0]) > 1 and self.__audio:
      pygame.mixer.music.load("../data/sounds/" + self.__music[0])
      pygame.mixer.music.play(-1)

    data = self.readLine()
    tempsounds = self.split(data, "\"")
    self.__sounds = []
    for sound in tempsounds:
      if len(sound) > 0 and self.__audio:
        self.__sounds.append(pygame.mixer.Sound("../data/sounds/" + sound))

    data = self.readLine()
    tempbackground = self.split(data, "\"")
    if len(tempbackground) > 0 and len(tempbackground[0]) > 1:
      self.__background = Image("../data/graphics/" + tempbackground[0])

  def nextSection(self):
    stop = False

    for sound in self.__sounds:
      sound.stop()

    if self.__currentsection < len(self.__sections):
      #print 'section:',self.__sections[self.__currentsection]
      self.__name = self.__sections[self.__currentsection][0]
      self.__displayed = self.__sections[self.__currentsection][1]
      self.__text = self.__sections[self.__currentsection][2]
      self.__played = self.__sections[self.__currentsection][3]
      self.__options = self.__sections[self.__currentsection][4]

      #print 'options length:', len(self.__sections[self.__currentsection][4])

      if self.__played is not None and len(self.__played) > 0:
        for sound in self.__played:
          sound.play()

      self.__currentsection += 1

      return

    while not stop and self.__index < len(self.__lines)-1:
      data = self.readLine()

      if len(data) < 1 or len(self.__options) > 0:
        continue

      if data[0] == "$":

        if data[1] == "n": #set name
          if len(data) == 2 or data[2] == " ":
            self.__name = None
          else:
            if data[2:].isdigit():
              self.__name = self.__names[int(data[2:])]
            else:
              temptext = self.replaceTextWithVarValues(data[2:].strip())
              self.__name = Text(temptext, self.__f, self.__screensize[0])

        elif data[1] == "i": #show images
          if len(data) == 2 or data[2] == " ":
            self.__displayed = [None, None, None]
          elif data.find("l") != -1:
            self.__displayed[0] = self.__images[int(data[2:data.find("l")])]
            self.__displayed[1] = None
          elif data.find("r") != -1:
            self.__displayed[1] = None
            self.__displayed[2] = self.__images[int(data[2:data.find("r")])]
          else:
            self.__displayed[0] = None
            self.__displayed[1] = self.__images[int(data[2:])]
            self.__displayed[2] = None

        elif data[1] == "p": #play sound
          if len(data) == 2 or data[2] == " " or not self.__audio:
            pass #play nothing?
          else:
            self.__sounds[int(data[2:])].play()
            self.__played.append(self.__sounds[int(data[2:])])

        elif data[1:3] == "br": #branch to a new file
          if platform.system() == "Windows":
            filepath = data[4:].replace("/", "\\")
          else:
            filepath = data[4:].replace("\\", "/")
          return MainScene("../data/scenes/" + filepath, self.__screensize, self.__audio, self.__variables)
          stop = True

        elif data[1] == "v": #variable manipulation
          tempdata = data.strip().split(" ")

          if len(tempdata) < 4 or tempdata[1].isdigit():
            print 'invalid variable data'
            continue

          if len(tempdata) == 4 and tempdata[3] in self.__variables:
            vartype = type(self.__variables[tempdata[1]])

            if tempdata[2] == "=":
              self.__variables[tempdata[1]] = (vartype)(self.__variables[tempdata[3]])

            elif tempdata[1] not in self.__variables:
              continue

            elif tempdata[2] == "+=":
              self.__variables[tempdata[1]] += (vartype)(self.__variables[tempdata[3]])
            elif tempdata[2] == "-=":
              self.__variables[tempdata[1]] -= (vartype)(self.__variables[tempdata[3]])
            elif tempdata[2] == "*=":
              self.__variables[tempdata[1]] *= (vartype)(self.__variables[tempdata[3]])
            elif tempdata[2] == "/=":
              self.__variables[tempdata[1]] /= (vartype)(self.__variables[tempdata[3]])

          elif len(tempdata) == 4 and tempdata[3].isdigit():
            if tempdata[2] == "=":
              self.__variables[tempdata[1]] = float(tempdata[3])

            elif tempdata[1] not in self.__variables:
              continue

            elif tempdata[2] == "+=":
              self.__variables[tempdata[1]] += float(tempdata[3])
            elif tempdata[2] == "-=":
              self.__variables[tempdata[1]] -= float(tempdata[3])
            elif tempdata[2] == "*=":
              self.__variables[tempdata[1]] *= float(tempdata[3])
            elif tempdata[2] == "/=":
              self.__variables[tempdata[1]] /= float(tempdata[3])

          else: #string, only supports assignment and addition
            if tempdata[2] == "=":
              self.__variables[tempdata[1]] = " ".join(tempdata[3:])

            elif tempdata[1] not in self.__variables:
              continue

            elif tempdata[2] == "+=":
              self.__variables[tempdata[1]] += str(float(tempdata[3]))

        elif data[1] == "?": #conditionals, does not support statements inside statements
          tempdata = data.strip().split(" ")
          executeblock = False

          if len(tempdata) < 4 or tempdata[1].isdigit() or tempdata[1] not in self.__variables:
            print 'invalid conditional data'
            continue

          if len(tempdata) == 4 and tempdata[3].isdigit():
            if not isinstance(self.__variables[tempdata[1]], float):
              print 'type inequility, expected float got', type(self.__variables[tempdata[1]])
              continue

            if tempdata[2] == "==":
              if self.__variables[tempdata[1]] == float(tempdata[3]):
                executeblock = True
            if tempdata[2] == "!=":
              if self.__variables[tempdata[1]] != float(tempdata[3]):
                executeblock = True
            elif tempdata[2] == "<=":
              if self.__variables[tempdata[1]] <= float(tempdata[3]):
                executeblock = True
            elif tempdata[2] == ">=":
              if self.__variables[tempdata[1]] >= float(tempdata[3]):
                executeblock = True
            elif tempdata[2] == "<":
              if self.__variables[tempdata[1]] < float(tempdata[3]):
                executeblock = True
            elif tempdata[2] == ">":
              if self.__variables[tempdata[1]] > float(tempdata[3]):
                executeblock = True

          elif len(tempdata) == 4 and tempdata[3] in self.__variables:
            if not isinstance(self.__variables[tempdata[1]], self.__variables[tempdata[3]]):
              print 'type inequility, expected', type(self.__variables[tempdata[3]]), 'got', type(self.__variables[tempdata[1]])
              continue

            if tempdata[2] == "==":
              if self.__variables[tempdata[1]] == self.__variables[tempdata[3]]:
                executeblock = True
            if tempdata[2] == "!=":
              if self.__variables[tempdata[1]] != self.__variables[tempdata[3]]:
                executeblock = True
            elif tempdata[2] == "<=":
              if self.__variables[tempdata[1]] <= self.__variables[tempdata[3]]:
                executeblock = True
            elif tempdata[2] == ">=":
              if self.__variables[tempdata[1]] >= self.__variables[tempdata[3]]:
                executeblock = True
            elif tempdata[2] == "<":
              if self.__variables[tempdata[1]] < self.__variables[tempdata[3]]:
                executeblock = True
            elif tempdata[2] == ">":
              if self.__variables[tempdata[1]] > self.__variables[tempdata[3]]:
                executeblock = True

          else: #comparison to text
            if not isinstance(self.__variables[tempdata[1]], str):
              print 'type inequility, expected str got', type(self.__variables[tempdata[1]])
              continue

            if tempdata[2] == "==":
              if self.__variables[tempdata[1]] == " ".join(tempdata[3:]):
                executeblock = True
            if tempdata[2] == "!=":
              if self.__variables[tempdata[1]] != " ".join(tempdata[3:]):
                executeblock = True
            elif tempdata[2] == "<=":
              if self.__variables[tempdata[1]] <= " ".join(tempdata[3:]):
                executeblock = True
            elif tempdata[2] == ">=":
              if self.__variables[tempdata[1]] >= " ".join(tempdata[3:]):
                executeblock = True
            elif tempdata[2] == "<":
              if self.__variables[tempdata[1]] < " ".join(tempdata[3:]):
                executeblock = True
            elif tempdata[2] == ">":
              if self.__variables[tempdata[1]] > " ".join(tempdata[3:]):
                executeblock = True

          if executeblock:
            self.__endlinemode = "?"
            tempstop = False

            while not tempstop:
              if self.__index >= len(self.__lines)-1: #skip to next block; this is bad btw.
                tempstop == True

              data = self.readLine()

              if data[0] == "{":
                tempstop = True
                continue   
          else:
            tempstop = False

            while not tempstop:
              if self.__index >= len(self.__lines)-1: #skip to next block; this is bad btw.
                tempstop == True

              data = self.readLine()

              if data[0] == "}":
                tempstop = True
                continue          

        elif data[1] == "c": #user questions, does not support statements inside statements
          if data[2] == "q" and len(data) > 4:
            self.__text = Text(data[4:], self.__f, self.__textBox.size()[2]-16)
            self.__endlinemode = "cq"
            data = self.readLine()
            self.__options.append((Text(data[4:], self.__f, self.__textBox.size()[2]-16), self.__index+1))

            tempstop = False

            while not tempstop:
              if self.__index >= len(self.__lines)-1: #skip to next block; this is bad btw.
                tempstop == True

              data = self.readLine()

              if data[0] == "}":
                data = self.readLine()
                if data[0:3] == "$ca":
                  self.__options.append((Text(data[4:], self.__f, self.__textBox.size()[2]-16), self.__index+1))
                else:
                  self.__lastoptionline = self.__index
                  #print 'lastoptionline:', self.__lastoptionline
                  tempstop = True
                  stop = True

      elif data[0] == "}": #end bracket thingy
        if self.__endlinemode == "cq":
          self.__index = self.__lastoptionline
        elif self.__endlinemode == "?":
          continue
      else:
        temptext = self.replaceTextWithVarValues(data)
        self.__text = Text(temptext, self.__f, self.__textBox.size()[2]-16)
        stop = True

      if stop:
        self.__currentsection += 1
        self.__sections.append((self.__name, list(self.__displayed), self.__text, list(self.__played), list(self.__options)))
        #print 'added section:', self.__sections[len(self.__sections)-1]
        self.__played = []

  def previousSection(self):
    if self.__currentsection <= 1:
      return

    self.__options = []
    self.__currentsection -= 2 #minus two, because we're currently on the next section!
    self.nextSection()

  def replaceTextWithVarValues(self, text):
    varbegin = text.find("${")
    while varbegin != -1:
      varend = text.find("}", varbegin)
      varname = text[varbegin+2:varend]
      if varname in self.__variables:
        tobereplaced = "${" + varname + "}"
        text = text.replace(tobereplaced, str(self.__variables[varname]))
      varbegin = text.find("${", varend)
    return text

  def split(self, datain, split):
    dataout = datain.split(split)

    for d in dataout:
      if len(d) == 0:
        dataout.remove('')
      if len(d.strip()) == 0:
        dataout.remove(' ')

    return dataout

  def readLine(self, amount = 0): #-1 is the last read line
    if amount == 0:
      self.__index += 1
    else:
      self.__index += amount
      if self.__index <= 0:
        self.__index = 0

    if self.__index >= len(self.__lines):
      self.__index = len(self.__lines)-1

    data = self.__lines[self.__index]
    data = data.strip()
    commentstart = data.find("#")

    if commentstart >= 0:
      data = data[0:commentstart]

    #print 'returning: ',data

    return data
    
